package cn.sytton.taffe.web.sys.service.impl;

import cn.sytton.taffe.framework.base.entity.PageParam;
import cn.sytton.taffe.framework.base.service.BaseService;
import cn.sytton.taffe.framework.util.SecurityUtil;
import cn.sytton.taffe.web.sys.entity.DeptEntity;
import cn.sytton.taffe.web.sys.entity.DeptUserEntity;
import cn.sytton.taffe.web.sys.mapper.DeptMapper;
import cn.sytton.taffe.web.sys.mapper.DeptUserMapper;
import cn.sytton.taffe.web.sys.service.IDeptService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 部门服务层
 *
 * @author skyrock
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class DeptService extends BaseService<DeptMapper, DeptEntity> implements IDeptService {

    private final DeptUserMapper deptUserMapper;

    @Override
    public void delete(String... ids) {
        for(String id : ids) {
            deleteChildren(id);
        }
        if (ids.length > 0) {
            super.delete(ids);
        }
    }
    private void deleteChildren(String parentId) {
        List<DeptEntity> list = baseMapper.findByParentId(parentId);
        for(DeptEntity dept : list) {
            deleteChildren(dept.getDeptId());
        }
        List<String> ids = list.stream().map(DeptEntity::getDeptId).collect(Collectors.toList());
        if (ids.size() > 0) {
            String[] idArray = ids.toArray(new String[0]);
            super.delete(idArray);
        }
    }

    @Override
    public List<DeptEntity> findByIds(String[] ids) {
        return super.listByIds(Arrays.asList(ids));
    }

    @Override
    public List<DeptEntity> findTree() {
        List<DeptEntity> rootList = baseMapper.findRoot();
        for (DeptEntity dept : rootList) {
            dept.setChildren(findChildren(dept.getDeptId()));
        }
        return rootList;
    }

    private List<DeptEntity> findChildren(String parentId) {
        List<DeptEntity> list = baseMapper.findByParentId(parentId);
        for (DeptEntity dept : list) {
            dept.setChildren(findChildren(dept.getDeptId()));
        }
        return list;
    }

    @Override
    public PageInfo<DeptUserEntity> findUserListPage(PageParam pp) {
        setPageParams(pp);
        String deptId = pp.getParams().get("deptId").toString();
        boolean exclude = pp.getParams().containsKey("exclude") && Boolean.parseBoolean(pp.getParams().get("exclude").toString());
        return new PageInfo<>(exclude ?  deptUserMapper.findByDeptIdForExclude(deptId) : deptUserMapper.findByDeptId(deptId));
    }

    @Override
    public void addUser(DeptUserEntity users) {
        int maxSeq = 0;
        if (users.getUserIds().size() > 0) {
            maxSeq = deptUserMapper.findMaxSeq(users.getDeptId());
        }
        for(String userId : users.getUserIds()) {
            maxSeq++;
            DeptUserEntity entity = new DeptUserEntity();
            entity.setUserId(userId);
            entity.setDeptId(users.getDeptId());
            entity.setSeq(maxSeq);
            deptUserMapper.create(entity);
        }
    }

    @Override
    public void removeUser(DeptUserEntity users) {
        if (users.getUserIds() != null && users.getUserIds().size() >0) {
            deptUserMapper.delete(new LambdaQueryWrapper<DeptUserEntity>()
                    .eq(DeptUserEntity::getDeptId, users.getDeptId())
                    .in(DeptUserEntity::getUserId, users.getUserIds()));
        }
    }

    @Override
    public void updateUserSeq(DeptUserEntity entity) {
        deptUserMapper.update(null, new LambdaUpdateWrapper<DeptUserEntity>()
                        .set(DeptUserEntity::getSeq, entity.getSeq())
                        .set(DeptUserEntity::getUpdatedUserId, SecurityUtil.getUserId())
                        .set(DeptUserEntity::getUpdatedTime, new Timestamp(new Date().getTime()))
                .eq(DeptUserEntity::getDeptId, entity.getDeptId())
                .eq(DeptUserEntity::getUserId, entity.getUserId()));
    }

    @Override
    public void refreshUserSeq(String deptId) {
        Map<String, Object> params = new HashMap<>();
        params.put("deptId", deptId);
        params.put("sort", "seq");
        List<DeptUserEntity> users = deptUserMapper.findListOfXml(params);
        for(int i = 0; i < users.size(); i++) {
            DeptUserEntity u = users.get(i);
            if (u.getSeq() != i + 1) {
                u.setSeq(i+1);
                updateUserSeq(u);
            }
        }
    }

    @Override
    public List<DeptEntity> findByUserId(String userId) {
        return baseMapper.findByUserId(userId);
    }
}
